<?php

namespace IDock\Insurance\LIHI\Request;

use Exception;
use IDock\Insurance\LIHI\LIHIEnums;
use IDock\Insurance\LIHI\Response\PremiumInquiryResponse;
use IDock\Visitor\Premium\PremiumChargingPileVisitor;
use IDock\Visitor\Premium\PremiumCoverageVisitor;
use IDock\Visitor\Premium\PremiumInquiryVisitor;
use IDock\Visitor\Premium\PremiumRelationVisitor;

class PremiumInquiryRequest extends AllLIHIRequest
{
    public $route = 'calculate/combinecalculate';

    protected $response = PremiumInquiryResponse::class;

    protected $urlTip = '报价接口';

    private $C16002 = false;

    private $C16003 = false;

    /*** @var  PremiumInquiryVisitor $visitor */
    protected $visitor;

    /**
     * @throws Exception
     */
    public function generate(): array
    {
        $this->agreementCode = $this->visitor->getExtInfoVisitor()->argc['agreementNo'] ?? '';
        $this->recordCode = $this->visitor->getExtInfoVisitor()->argc['recordCode'] ?? '';

        $this->flowId = $this->visitor->getExtInfoVisitor()->argc['flowId'] ?? '';
        $data = [
            'tprpTmainDto' => $this->mainData(),
            'tprpTitemCarDto' => $this->carData(),
            'tprptCarOwnerDto' => $this->getOwnerData(),
            'tprptApplicantDto' => $this->getApplicant(),
            'tprptInsuredDto' => $this->insuredList(),
            'tprpTitemKindListDto' => $this->getCoverageList(),
        ];

        if ($chargingList = $this->chargingList()) {
            $data['tprpTitemKindSubListDto'] = $chargingList;
        }
        if ($data['tprpTmainDto']['combineFlag'] != 'MOTOR') {
            $data['prpTcarshipTaxDto'] = $this->carShipTax();
        }

        if ($this->visitor->getDeviceList()) {
            $data['deviceList'] = $this->getDeviceList();
        }

        return $data;
    }

    /**
     * @return array
     * @throws Exception
     */
    private function getOwnerData(): array
    {
        $model = $this->visitor->getOwnerVisitor();
        return $this->getUserInfo($model);
    }

    /**
     * @return array
     * @throws Exception
     */
    private function getApplicant(): array
    {
        return $this->getUserInfo($this->visitor->getApplicantVisitor());
    }

    /**
     * @return array
     * @throws Exception
     */
    private function insuredList(): array
    {
        return $this->getUserInfo($this->visitor->getInsuredVisitor());
    }

    /**
     * @param PremiumRelationVisitor $model
     * @return array
     * @throws Exception
     */
    private function getUserInfo(PremiumRelationVisitor $model): array
    {

        $arr = [
            'name' => $model->name,
            'idType' => LIHIEnums::$certificateTypeCode[$model->certificateTypeCode] ?? '',
            'idNo' => $model->certificateNo,
            'cellPhoneNo' => $model->mobile,
            'address' => $model->address,
            'email' => $model->email,
        ];
        if (empty($arr['idType'])) {
            throw new Exception("不支持该证件类型");
        }
        if ($model->typeCode == 'R1') {
            $arr['gental'] = $this->getGenderByIDcard($model->certificateNo);
            $arr['effectedDate'] = $model->certificateStartDate;
            $arr['expiredDate'] = $model->certificateEndDate;
            $arr['natureOfRole'] = '1';
        } else {
            $arr['certiStartDate'] = $model->certificateStartDate;
            $arr['certiEndDate'] = $model->certificateEndDate;
            $arr['natureOfRole'] = '2';
        }

        $arr['idType'] = LIHIEnums::$certificateTypeCode[$model->certificateTypeCode] ?? '';
        return $arr;
    }

    /**
     * 主信息
     * @return array
     */
    private function mainData(): array
    {
        $data = [
            'combineFlag' => 'COMBINE',//COMBINE-联合单;MOTOR-商业;MTPL-交强
            'proposalNo' => '',//投保单号 单交强不传
            'mtplProposalNo' => '',//交强险投保单号 单商业不传
            'salerNumber' => '',//销售人员代码
            'salerName' => '',//销售人员名称
            'startDate' => '',//商业险起期
            'startHour' => '',//商业险起期(小时)
            'endDate' => '',//商业险止期
            'endHour' => '',//商业险止期(小时)
            'mtplStartDate' => '',//交强险起期
            'mtplStartHour' => '',//交强险起期(小时)
            'mtplEndDate' => '',//交强险止期
            'mtplEndHour' => '',//交强险止期(小时)
            'newEnergyFlag' => $this->visitor->isNewEnergy ? 1 : 0,//是否投保新能源条款标识
            'callBackUrl' => '',
        ];

        //修改自主定价系数
        if ($this->visitor->getExtInfoVisitor()->selfPricingFactor) {
            $data['autonomyValue'] = $this->visitor->getExtInfoVisitor()->selfPricingFactor;
            $data['chgAutonomyValueFlag'] = '1';
        }

        //险种联合类型
        //单交强
        if ($this->visitor->ciStartData) {
            $data['combineFlag'] = 'MTPL';
        }
        //单商业
        if ($this->visitor->biStartData) {
            $data['combineFlag'] = 'MOTOR';
        }
        //交商同保
        if ($this->visitor->biStartData && $this->visitor->ciStartData) {
            $data['combineFlag'] = 'COMBINE';
        }

        //交强
        if ($data['combineFlag'] == 'MTPL' or $data['combineFlag'] == 'COMBINE') {

            $data['mtplStartDate'] = date('Y-m-d', strtotime($this->visitor->ciStartData));

            //非即时起保
            if (date('Y-m-d') != date('Y-m-d',strtotime($this->visitor->ciStartData))) {
                $data['mtplStartHour'] = '0';
                $data['mtplEndDate'] = date('Y-m-d', strtotime('+1 year -1 day',strtotime($this->visitor->ciStartData)));
                $data['mtplEndHour'] = '24';

            } else {
                $data['mtplStartHour'] = date('H',strtotime($this->visitor->ciStartData));
                $data['mtplEndDate'] = date('Y-m-d', strtotime('+1 year',strtotime($this->visitor->ciStartData)));

                if ($data['combineFlag'] == 'COMBINE') {
                    $data['mtplEndHour'] = date('H',strtotime($this->visitor->ciStartData));
                } else {
                    //单交强-即时起保
                    $data['mtplEndHour'] = date('H',strtotime($this->visitor->ciStartData));
                }
            }
        }
        //商业
        if ($data['combineFlag'] == 'MOTOR' or $data['combineFlag'] == 'COMBINE') {

            $data['startDate'] = date('Y-m-d', strtotime($this->visitor->biStartData));

            //非即时起保
            if (date('Y-m-d') != date('Y-m-d',strtotime($this->visitor->biStartData))) {
                $data['startHour'] = '0';

                $data['endDate'] = date('Y-m-d', strtotime('+1 year -1 day',strtotime($this->visitor->biStartData)));
                $data['endHour'] = '24';
            } else {
                $data['startHour'] = date('H',strtotime($this->visitor->biStartData));

                $data['endDate'] = date('Y-m-d', strtotime('+1 year -1 day',strtotime($this->visitor->biStartData)));
                $data['endHour'] = '24';
            }


            //$data['endDate'] = date('Y-m-d', strtotime($this->visitor->biEndData));
        }

        return $data;
    }

    /**
     * 车辆信息
     * @return array
     * @throws Exception
     */
    private function carData(): array
    {
        $data = [
            'runAreaCode' => '10',//行驶区域代码 默认全是四川
            'carInsuredRelation' => $this->visitor->getOwnerVisitor()->typeCode == 'R1' ? '3' : '4',//车主类型
            'licenseKindCode' => '02',//小型汽车
            'licenseNo' => $this->visitor->getVehicleVisitor()->licenseNo,
            'carKindCode' => LIHIEnums::$carKindCode[$this->visitor->getVehicleVisitor()->carKindCode] ?? '',//车辆种类
            'exhaustScale' => $this->visitor->getVehicleVisitor()->vehicleExhaust,
            'tonCount' => (string)floatval(floatval($this->visitor->getVehicleVisitor()->vehicleTonnage ?? 0) / 1000),
            'seatCount' => $this->visitor->getVehicleVisitor()->vehicleSeat,

            'useNatureCode' => $this->getUseNatureCode(
                $this->visitor->getVehicleVisitor()->useNatureCode,
                $this->visitor->getVehicleVisitor()->causeType,
                $this->visitor->getVehicleVisitor()->carKindCode
            ),

            'engineNo' => $this->visitor->getVehicleVisitor()->engineNo,
            'vinNo' => $this->visitor->getVehicleVisitor()->vin,
            'modelCode' => $this->visitor->getVehicleVisitor()->vehicleModelCode,
            'whethelicenses' => $this->visitor->getVehicleVisitor()->isNewVehicle ? '0' : '1',
            'whethercar' => '0',//是否外地车
            'fuelType' => array_search($this->visitor->getVehicleVisitor()->energyTypeCode, LIHIEnums::$energyType) ?? '',
            'enrollDate' => $this->visitor->getVehicleVisitor()->firstRegisterDate,
            'purchasePrice' => $this->visitor->getVehicleVisitor()->vehiclePrice,
            'vehicleCategoryCode' => $this->visitor->getVehicleVisitor()->vehicleStyleCode,
            'vehicleModel' => $this->visitor->getVehicleVisitor()->vehicleModel,

            'chgOwnerFlag' => '0',
            'mtplChgOwnerFlag' => '0',
            //'mtplChgOwnerFlag' => $this->visitor->getVehicleVisitor()->isCiTransfer,
            'poWeight' => $this->visitor->getVehicleVisitor()->wholeWeight,
            'loanVehicleFlag' => '0',
            'vehicleBrand' => $this->visitor->getVehicleVisitor()->argc['brandName'] ?? '',
            //进口/国产
            'countryCode' => '',
            //车身颜色
            'carColor' => LIHIEnums::$vehicleColor[$this->visitor->vehicleVisitor->vehicleColor] ?? '',
        ];

        if ($this->visitor->vehicleVisitor->carCertificateType) {
            $data['certificateDate'] = $this->visitor->vehicleVisitor->carCertificateDate;
            $data['certificateNo'] = $this->visitor->vehicleVisitor->carCertificateNo;
            $data['certificateType'] = (string)(int)$this->visitor->vehicleVisitor->carCertificateType;
        }

        //优化客车荷载质量
        if ($data['carKindCode'] == 'A0') {
            $data['tonCount'] = '0';
        }

        if ($this->visitor->getVehicleVisitor()->vehicleImport == 'I1') {
            $data['countryCode'] = '国产车';
        }
        if ($this->visitor->getVehicleVisitor()->vehicleImport == 'I2') {
            $data['countryCode'] = '合资车';
        }
        if ($this->visitor->getVehicleVisitor()->vehicleImport == 'I3') {
            $data['countryCode'] = '进口车';
        }

        if ($this->visitor->getOwnerVisitor()->typeCode != 'R1') {
            $data['companyType'] = '0';
        }
        if (empty($data['carKindCode'])) {
            throw new Exception("不支持该车辆种类");
        }

        if ($this->visitor->getVehicleVisitor()->isTransfer) {
            $data['chgOwnerFlag'] = '1';
            $data['transferDate'] = $this->visitor->getVehicleVisitor()->transferDate;
        }

        if ($this->visitor->getVehicleVisitor()->isCiTransfer) {
            $data['mtplChgOwnerFlag'] = '1';
            $data['transferDate'] = $this->visitor->getVehicleVisitor()->transferDate;
        }

        return $data;
    }

    /**
     * 险种信息
     * @return array
     */
    private function getCoverageList(): array
    {
        $list = [];
        $no = 1;

        $coverageList = $this->visitor->getCoverageVisitorList();
        $coverageList = array_combine(array_column($coverageList, 'coverageCode'), $coverageList);

        foreach ($coverageList as $coverage) {

            /*** @var PremiumCoverageVisitor $coverage */

            //交强险去除
            if ($coverage->coverageCode == 'C01001') {
                continue;
            }
            if ($coverage->coverageCode == 'C16002') {
                $this->C16002 = true;
                continue;
            }
            if ($coverage->coverageCode == 'C16003') {
                $this->C16003 = true;
                continue;
            }
            $one = [
                'itemKindNo' => (string)$no,
                'kindCodeMain' => LIHIEnums::$coverageCode[$coverage->coverageCode],
                'kindNameMain' => LIHIEnums::$coverageName[$coverage->coverageCode],
                'quantityMain' => (string)intval($coverage->quantity),
                'amountMain' => $coverage->amount,
            ];

            //车损险保额
            if (in_array($coverage->coverageCode,['C02001','C12001'])) {
                $one['amountMain'] = $this->visitor->getVehicleVisitor()->negotiatedValue?: $this->visitor->getVehicleVisitor()->actualValue;
            }

            //乘客险
            if (in_array($coverage->coverageCode, ['C05001', 'C15001',])) {
                $one['quantityMain'] = strval($this->visitor->getVehicleVisitor()->vehicleSeat - 1);
                $one['unitAmountMain'] = $coverage->unitAmount;
            }

            //乘客险保外
            if (in_array($coverage->coverageCode, ['C05002', 'C15002'])) {
                $one['quantityMain'] = strval($this->visitor->getVehicleVisitor()->vehicleSeat - 1);
                $one['unitAmountMain'] = $coverage->amount;
                $one['amountMain'] = $one['quantityMain'] * $one['unitAmountMain'];
            }
            //医疗外 乘客
            if (in_array($coverage->coverageCode, ['C05003', 'C15003'])) {
                $one['quantityMain'] = strval($this->visitor->getVehicleVisitor()->vehicleSeat - 1);
                $one['unitAmountMain'] = '';
                $one['amountMain'] = $coverage->amount;
            }

            //绝对免赔率
            if (in_array($coverage->coverageCode, ['C02006', 'C03005', 'C04004', 'C05004', 'C12006', 'C13005', 'C14004', 'C15004'])) {
                $one['quantityMain'] = $coverage->deductionRate;
            }
            //单份险种费用
            if (in_array($coverage->coverageCode, ['C02003', 'C12003', 'C16003', 'C05004', 'C15004'])) {
                $one['unitAmountMain'] = $coverage->unitAmount;
                $one['amountMain'] = (string)round((floatval($one['quantityMain']) * floatval($one['unitAmountMain'])), 2);
            }

            //司机险
            //if (in_array($coverage->coverageCode, ['C04001', 'C04002', 'C04003', 'C14001', 'C14002', 'C14003'])) {
            //
            //}

            $no += 1;

            $list[] = $one;
        }
//        //非车
//        if(!empty($this->visitor->getNonCarInquiryVisitor()->getNonCarList())){
//            /**@var NonCarProductVisitor $noCarPlan */
//            $noCarPlan = $this->visitor->getNonCarInquiryVisitor()->getNonCarList()[0] ?? [];
//            $amount = 0;
//            foreach ($noCarPlan->subCoverage as $val){
//                /**@var NonCarSubCoveragePrinter $val */
//                $amount += floatval($val->amount);
//            }
//            $list[] = [
//                'itemkindNo' => count($list) + 1,
//                'kindCode' => $noCarPlan->productCode,
//                'quanTity' => intval($noCarPlan->insuredNum),
//                'unitAmount' => $noCarPlan->premium,
//                'amount' => floatval($noCarPlan->premium *  $noCarPlan->insuredNum),
//                'kindFlag' => '1',
//            ];
//        }
        return $list;
    }

    /**
     * 充电桩
     * @return array
     */
    private function chargingList(): array
    {
        if (!$this->C16003 and !$this->C16002) {
            return [];
        }
        $list = [];
        $no = 1;
        foreach ($this->visitor->getChargingPileVisitorList() as $visitor) {
            /*** @var PremiumChargingPileVisitor $visitor */
            //C1
            if ($this->C16002) {
                $kindList = [
                    'itemkindNo' => (string)$no,
                    'kindCodeMain' => 'C203',
                    'kindNameMain' => LIHIEnums::$coverageName['C16002'],
                    'unitAmountMain' => $visitor->lossAmount,
                    'amountMain' => $visitor->lossAmount,
                    'chargingPostType' => $visitor->chargingPileType,
                    'chargingPostCode' => $visitor->chargingPileCode,
                    'chargingPostAddress' => $visitor->chargingPileAddress,
                    'chargingPostKind' => LIHIEnums::$chargingPileKind[$visitor->chargingPileKind],
                    'chargingPostAddressType' => LIHIEnums::$chargingPileAddressType[$visitor->chargingPileAddressType],
                    'chargingPostYearLimit' => LIHIEnums::$chargingPileYearLimit[$visitor->chargingPileYearLimit],
                ];
                $list[] = $kindList;
                $no += 1;
            }

            //C2
            if ($this->C16003) {
                $kindList = [
                    'itemkindNo' => (string)$no,
                    'kindCodeMain' => 'C204',
                    'kindNameMain' => LIHIEnums::$coverageName['C16003'],
                    'unitAmountMain' => $visitor->liabilityAmount,
                    'amountMain' => $visitor->liabilityAmount,
                    'chargingPostType' => $visitor->chargingPileType,
                    'chargingPostCode' => $visitor->chargingPileCode,
                    'chargingPostAddress' => $visitor->chargingPileAddress,
                    'chargingPostKind' => LIHIEnums::$chargingPileKind[$visitor->chargingPileKind],
                    'chargingPostAddressType' => LIHIEnums::$chargingPileAddressType[$visitor->chargingPileAddressType],
                    'chargingPostYearLimit' => LIHIEnums::$chargingPileYearLimit[$visitor->chargingPileYearLimit],
                ];

                $list[] = $kindList;
                $no += 1;
            }
        }
        return $list;

    }

    /**
     * 车船税
     * @return array
     * @throws Exception
     */
    private function carShipTax(): array
    {
        $taxVisitor = $this->visitor->getCarTaxVisitor();

        $arr = [
            'taxpayerName' => $taxVisitor->taxpayerName,
            'taxPayerIdentificationCode' => $taxVisitor->taxpayerCertificateNo,
            'taxConditionCode' => LIHIEnums::$taxTypeCode[$taxVisitor->taxTypeCode] ?? '',
            'taxDocumentNumber' => $taxVisitor->taxDocumentNumber,
            'deductionDocumentNumber' => '',//减免税凭证号
        ];
        if ($arr['taxConditionCode'] == 'P') {
            $arr['taxDocumentDate'] = $taxVisitor->taxDocumentDate;
            $arr['taxPaidAreaCode'] = $taxVisitor->taxPaidAreaCode;
        }
        if (empty($arr['taxConditionCode'])) {
            throw new Exception("不支持该纳税类型");
        }
        return $arr;
    }

    /**
     * 通过身份证获取性别
     * @param $idCard
     * @return string
     * @throws Exception
     */
    private function getGenderByIDcard($idCard): string
    {
        if (strlen($idCard) != 18) {
            throw new Exception("身份证位数不合法");
        }
        $gender = intval(substr($idCard, 16, 1)) % 2;
        return $gender ? '1' : '2';
    }

    /**
     * 新增设备
     * @return array
     */
    private function getDeviceList(): array
    {
        $deviceList = [];
        foreach ($this->visitor->getDeviceList() as $k => $device) {
            $deviceList[] = [
                'serialNo' => $k + 1,
                'itemNo' => $device->deviceName,
                'deviceName' => $device->deviceName,
                'quantity' => $device->quantity,
                'buyDate' => $device->buyDate,
                'purchasePrice' => $device->purchasePrice,
                'remark' => '',
            ];
        }

        return $deviceList;
    }

    /**
     * 车辆使用性质
     * @param $useNatureCode
     * @param $causeType
     * @param $carKindCode
     * @return mixed|string
     */
    public static function getUseNatureCode($useNatureCode, $causeType, $carKindCode)
    {
        //家庭自用客车
        if ($causeType == '001' and $carKindCode == '100') {
            return '8A';
        }
        //非运营货运
        if ($causeType == '001' and ($carKindCode == '200' or $carKindCode == '210')) {
            return '8E';
        }
        //非运营
        if ($useNatureCode == '01') {
            //非运营企业
            if ($causeType == '003') {
                return '8B';
            }
            //非运营机关
            if ($causeType == '002') {
                return '8C';
            }
            //非运营货运
            if ($carKindCode == '200' or $carKindCode == '210') {
                return '8E';
            }
            //非营业挂车
            if ($carKindCode == '320') {
                return '8I';
            }
        }
        //运营
        if ($useNatureCode == '02') {
            return LIHIEnums::$causeType[$causeType] ?? '';
        }

        //特种车
        if ($carKindCode == '500') {
            return '8F';
        }

        return '8A';
    }
}
